package com.hup.utils.jna.common;

import com.sun.jna.Pointer;
import com.sun.jna.platform.WindowUtils;
import com.sun.jna.platform.win32.Advapi32Util;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef.DWORD;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinDef.RECT;
import com.sun.jna.platform.win32.WinReg;
import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;

import java.util.ArrayList;

/**
 * 针对winApi的工具类
 *
 * @author hugan
 * @date 2020/11/20
 */
@Log4j2
@NoArgsConstructor
@SuppressWarnings("SpellCheckingInspection")
public abstract class Win32Util {

    /**
     * 获取当前前置程序的文件路径
     *
     * @return nullable, emptyAble-如锁屏界面/权限不足时的任务管理器:会返回null或空字符串
     */
    public static String getFrontApp() {
        HWND foregroundWindow = User32.INSTANCE.GetForegroundWindow();
        if (foregroundWindow == null) return null;//锁屏界面会返回null
        return getProcessPath(foregroundWindow);
    }

    /**
     * 获取默认浏览器的文件路径;使用读取注册表的方法
     */
    public static String getDefaultBrowserPath() {
        //如:["xxx.exe" "%1"]
        String value = Advapi32Util.registryGetStringValue(WinReg.HKEY_CLASSES_ROOT, "http\\shell\\open\\command", "");
        //提取第一对引号里的内容
        StringBuilder sb = new StringBuilder(value);
        int indexOf = sb.indexOf("\"", 1);
        sb.delete(indexOf, sb.length());
        sb.deleteCharAt(0);
        return sb.toString();
    }

    /**
     * 列出用户窗口
     */
    public static ArrayList<HWND> listWindow() {
        ArrayList<HWND> res = new ArrayList<>();

        User32 user32 = User32.INSTANCE;
        HWND hwnd = user32.GetWindow(user32.GetDesktopWindow(), new DWORD(User32.GW_CHILD));
        while (hwnd != null) {
            if (user32.IsWindowVisible(hwnd) && user32.GetWindowTextLength(hwnd) > 0) {
                res.add(hwnd);
            }
            hwnd = user32.GetWindow(hwnd, new DWORD(User32.GW_HWNDNEXT));
        }
        return res;
    }

    public static boolean setWindowOnTop(HWND hwnd, boolean isOnTop) {
        //https://docs.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-setwindowpos
        return User32.INSTANCE.SetWindowPos(hwnd,
                isOnTop ? new HWND(new Pointer(-1)) : new HWND(new Pointer(-2)),
                0, 0, 0, 0, User32.SWP_NOSIZE | User32.SWP_NOMOVE);
    }

    /**
     * @return 窗口是否置顶
     */
    public static boolean isWindowOnTop(HWND hwnd) {
        return (User32.INSTANCE.GetWindowLong(hwnd, User32.GWL_EXSTYLE) & User32.WS_EX_TOPMOST) != 0;
    }

    public static boolean setWindowSize(HWND hwnd, int width, int height) {
        //https://docs.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-setwindowpos
        return User32.INSTANCE.SetWindowPos(hwnd, null,
                0, 0, width, height,
                /*
                SWP_NOMOVE 禁止移动窗口。
                SWP_NOZORDER 禁止改变窗口的堆叠顺序。
                SWP_NOOWNERZORDER 禁止改变窗口所属的堆叠顺序。
                */
                User32.SWP_NOMOVE | User32.SWP_NOZORDER | User32.SWP_NOOWNERZORDER);
    }

    /**
     * width = rect.right - rect.left;
     * height = rect.bottom - rect.top;
     */
    public static boolean getWindowRect(HWND hwnd, RECT rect) {
        return User32.INSTANCE.GetWindowRect(hwnd, rect);
    }

    /**
     * 获取窗口标题
     */
    public static String getWindowTitle(HWND hwnd) {
        char[] temp = new char[255];
        int readLength = User32.INSTANCE.GetWindowText(hwnd, temp, temp.length);
        return new String(temp, 0, readLength);
    }

    /**
     * 获取窗口进程路径
     *
     * @return nullable, emptyAble-如锁屏界面/权限不足时的任务管理器:会返回null或空字符串
     */
    public static String getProcessPath(HWND hwnd) {
        try {
            return WindowUtils.getProcessFilePath(hwnd);
        } catch (Exception e) {
            log.warn("获取窗口进程路径异常={}, {}", e.getMessage(), hwnd);
            return null;
        }
    }

}
